package com.szp.lagou.dubbo.filerDemo.filter;

import com.szp.lagou.dubbo.filerDemo.Context.IpContext;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Activate(group = {CommonConstants.CONSUMER})//,CommonConstants.PROVIDER
public class TransportIPFilter implements Filter, Runnable {
    private static ConcurrentHashMap<String, List<Integer>> methodCallTimes = new ConcurrentHashMap<>();
    private static Logger logger = LoggerFactory.getLogger(TransportIPFilter.class);

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
//        logger.info("记录rpc调用时间"+ clientIp);
        long startTime = System.currentTimeMillis();
        try {
            String methodName = invoker.getInterface().getName() + "." + invocation.getMethodName();
            System.out.println("methodName: " + methodName);
//            System.out.println("methodName: " + methodName);
            // 执行方法
            Result result = invoker.invoke(invocation);

            List<Integer> times = methodCallTimes.get(methodName);
            if (null == times) {
                times = new ArrayList<>();
                methodCallTimes.put(methodName, times);
            }
            int time = (int) (System.currentTimeMillis() - startTime);
            times.add(time);
            System.out.println("invoke time:" + (time) + "毫秒");

            return result;
        } catch(Exception e){
            logger.error("调用rpc服务发生错误{}",e);
            return null;
        }
    }

    @Override
    public void run() {
        // 遍历methodCallTimes, 计算top90，top95
        while (true) {
            Set<Map.Entry<String, List<Integer>>> entrySet = methodCallTimes.entrySet();
            for (Map.Entry<String, List<Integer>> stringListEntry : entrySet) {
                String methodName = stringListEntry.getKey();
                List<Integer> times = stringListEntry.getValue();
                methodCallTimes.put(methodName, new ArrayList<>());
                calculateTopTime(methodName, times);
            }
            try {
                Thread.currentThread().sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private void calculateTopTime(String methodName, List<Integer> times) {
        int size = times.size();
        if(size == 0){
            System.out.println("方法" + methodName + "在5秒内无其他服务调用！");
            return;
        }
        Collections.sort(times);
        int top90Index = (int)(0.9 * size);
        int top99Index = (int)(0.99 * size);
        System.out.println("方法 " + methodName + " 5秒内总调用次数:" + size);
        System.out.println("方法 " + methodName + " top90调用时间:" + times.get(top90Index));
        System.out.println("方法 " + methodName + " top99调用时间:" + times.get(top99Index));
    }
}
